import random

from django.shortcuts import render
from django.views import View
# 导入验证码插件包
from verification.libs.captcha.captcha import captcha
# 引入redis
from django_redis import get_redis_connection
# 引入http
from django import http
# 导入全局常量
from dj_shop.utils import constants
# 导入响应参数
from dj_shop.utils.responseCode import RESP_CODE, RESP_MESSAGE

# 导入发送验证码
from verification.libs.communicationCloud.SendTemplateSMS import SendSMS

# 引入日志
import logging

# 日志别名
logger = logging.getLogger('django')

# 引入外部celery
from celery_task.sms.tasks import send_sms_code


# 1.获取图形验证码
class GetVerificationCode(View):
    def get(self, request, uuid):
        print("获取验证码：", uuid)
        # 1.生成验证码和图片，注意容联云更改了发送策略，需要是数字 TODO
        CHAR_SET = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
        CAPTCHA_LEN = 4
        code, image = captcha.generate_captcha()
        # 存入redis[2]号库，dev.py中配置了redis的别名=
        redisCon = get_redis_connection('verification_code')
        # 存储数据：设置过期时间setex(key,expires（单位秒）默认5分钟,value)及key+value
        redisCon.setex('img_code_%s' % uuid, constants.IMAGE_CODE_REDIS_EXPIRES, code)

        # 日志输入
        # logger.info("验证码：",redisCon.get('img_code_%s' % uuid).decode())
        # 响应图片
        return http.HttpResponse(image, content_type='image/jpg')


# 2.校验验证码
class CheckVerificationCode(View):
    def get(self, request, mobile, code, uuid):
        print("获取到的mobile: " + mobile + "code：", code, "uuid：", uuid)
        respData = {
            'code': RESP_CODE.OK
        }
        return http.HttpResponse()


# 3.发送短信
class SendShortMessage(View):
    def get(self, request, mobile):

        respData = {
            'code': RESP_CODE.OK,
            'respMsg': "成功！"
        }
        # 1.获取验证码：获取请求体中的参数，ajax请求json
        imgCodeClient = request.GET.get('code')
        print("发送短信：获取到的mobile: " + mobile, "code=", imgCodeClient)

        if not imgCodeClient:
            respData['code'] = RESP_CODE.IMAGECODEERR
            respData['respMsg'] = '验证码不能为空！'
            return http.JsonResponse(respData)
        uuid = request.GET.get('uuid')
        # 2.对比验证码
        if not all([imgCodeClient, uuid]):
            return "缺少必传的参数！"

        # 2.0获取redis存储的验证码，python3中的redis存取都转为了bytes
        redisCon = get_redis_connection('verification_code')
        imgCodeServer = ""
        if redisCon.get('img_code_%s' % uuid):
            # 将bytes转为strin
            imgCodeServer = redisCon.get('img_code_%s' % uuid).decode()
        print("服务端验证码：", imgCodeServer)
        if imgCodeServer is None or imgCodeServer == '':
            respData['code'] = RESP_CODE.IMAGECODEDEAD
            respData['respMsg'] = '验证码已过期！'
            return http.JsonResponse(respData)
        # 2.1 转下写判断：成功，删除验证码
        elif imgCodeServer != '' and imgCodeClient.lower() != imgCodeServer.lower():
            # redisCon.delete('img_code_%s' % uuid)
            respData['code'] = RESP_CODE.IMAGECODEERR
            respData['respMsg'] = '验证码输入错误！'
            return http.JsonResponse(respData)

        smsCodeExpire = redisCon.get('sms_code_expire_%s' % mobile)
        if not smsCodeExpire:
            # 3.生成短信随机码：%04d 输出四位数，不足的补0
            shortCode = '%04d' % random.randint(0, 9999)
            print('发送的验证码：', shortCode)
            # 使用pipeline，创建redis管道
            pipLine = redisCon.pipeline()
            # 执行命令封装入redis管道
            pipLine.setex('sms_code_%s' % mobile, constants.SMS_CODE_REDIS_EXPIRES, shortCode)
            pipLine.setex('sms_code_expire_%s' % mobile, constants.SEND_SMS_CODE_INTERVAL, "expire time 60s")
            # 执行redis管道
            pipLine.execute()

            # 4.保存短信随机码
            # redisCon.setex('sms_code_%s' % mobile, constants.SMS_CODE_REDIS_EXPIRES, shortCode)
            # 保存短信随机码，同时保存一个过期时间为60秒，避免用户通过postman等调试工具越过前端进行请求
            # 我们这里限制了1分钟发一条。容联云默认配置了一个手机号1小时内，最多发5条短信
            # redisCon.setex('sms_code_expire_%s' % mobile, constants.SEND_SMS_CODE_INTERVAL, "expire time 60s")

            # 5.【 非celery异步 】发送短信验证码
            # SendSMS().send(mobile, [shortCode, constants.IMAGE_CODE_REDIS_EXPIRES // 60], constants.SEND_SMS_TEMPLATE_ID)

            # 5.【 celery异步任务处理 】发送通过外部celery_task的sms封装包，因被celery装饰器@celeryApp.task装饰 ==>必须接delay延时发送
            send_sms_code.delay(mobile, shortCode)

            # logger.info("发送的短信验证码：",redisCon.get('sms_code_%s' % mobile))
            print("respData: ", respData)
            return http.JsonResponse(respData)
        else:
            respData['code'] = RESP_CODE.THROTTLINGERR
            respData['respMsg'] = '小伙子，你意图不轨！'
            return http.JsonResponse(respData)
